const express = require('express');
const { body, query, param, validationResult } = require('express-validator');
const { Exam, Course, User } = require('../models');
const { authenticate, authorize } = require('../middleware/auth');
const { AppError, ValidationError } = require('../middleware/errorHandler');
const config = require('../config/config');
const logger = require('../config/logger');

const router = express.Router();

// 验证规则
const createExamValidation = [
  body('title')
    .notEmpty()
    .withMessage('考试标题不能为空')
    .isLength({ min: 1, max: 200 })
    .withMessage('考试标题长度必须在1-200个字符之间'),
  
  body('description')
    .optional()
    .isLength({ max: 2000 })
    .withMessage('考试描述不能超过2000个字符'),
  
  body('type')
    .isIn(['quiz', 'assignment', 'midterm', 'final', 'practice'])
    .withMessage('考试类型无效'),
  
  body('level')
    .isIn(['beginner', 'intermediate', 'advanced', 'expert'])
    .withMessage('考试难度级别无效'),
  
  body('courseId')
    .optional()
    .isUUID()
    .withMessage('课程ID格式无效'),
  
  body('duration')
    .isInt({ min: 1 })
    .withMessage('考试时长必须是正整数（分钟）'),
  
  body('totalScore')
    .isDecimal({ decimal_digits: '0,2' })
    .withMessage('总分格式无效')
    .custom((value) => {
      if (parseFloat(value) <= 0) {
        throw new Error('总分必须大于0');
      }
      return true;
    }),
  
  body('passingScore')
    .isDecimal({ decimal_digits: '0,2' })
    .withMessage('及格分数格式无效')
    .custom((value, { req }) => {
      const totalScore = parseFloat(req.body.totalScore);
      const passingScore = parseFloat(value);
      if (passingScore < 0 || passingScore > totalScore) {
        throw new Error('及格分数必须在0到总分之间');
      }
      return true;
    }),
  
  body('maxAttempts')
    .optional()
    .isInt({ min: 1 })
    .withMessage('最大尝试次数必须是正整数'),
  
  body('startTime')
    .optional()
    .isISO8601()
    .withMessage('开始时间格式无效'),
  
  body('endTime')
    .optional()
    .isISO8601()
    .withMessage('结束时间格式无效')
    .custom((value, { req }) => {
      if (value && req.body.startTime) {
        const startTime = new Date(req.body.startTime);
        const endTime = new Date(value);
        if (endTime <= startTime) {
          throw new Error('结束时间必须晚于开始时间');
        }
      }
      return true;
    }),
  
  body('isRandomOrder')
    .optional()
    .isBoolean()
    .withMessage('随机顺序标识必须是布尔值'),
  
  body('showResultsImmediately')
    .optional()
    .isBoolean()
    .withMessage('立即显示结果标识必须是布尔值'),
  
  body('allowReview')
    .optional()
    .isBoolean()
    .withMessage('允许回顾标识必须是布尔值'),
  
  body('questions')
    .optional()
    .isArray()
    .withMessage('题目必须是数组格式'),
  
  body('accessCode')
    .optional()
    .isLength({ min: 4, max: 20 })
    .withMessage('访问码长度必须在4-20个字符之间')
];

const updateExamValidation = [
  param('id')
    .isUUID()
    .withMessage('考试ID格式无效'),
  
  ...createExamValidation.map(validation => {
    // 将所有字段设为可选
    if (validation.builder && validation.builder.fields) {
      validation.builder.fields.forEach(field => {
        if (field !== 'id') {
          validation.optional();
        }
      });
    }
    return validation;
  })
];

const getExamsValidation = [
  query('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('页码必须是正整数'),
  
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('每页数量必须在1-100之间'),
  
  query('type')
    .optional()
    .isIn(['quiz', 'assignment', 'midterm', 'final', 'practice'])
    .withMessage('考试类型无效'),
  
  query('level')
    .optional()
    .isIn(['beginner', 'intermediate', 'advanced', 'expert'])
    .withMessage('难度级别无效'),
  
  query('status')
    .optional()
    .isIn(['draft', 'published', 'archived'])
    .withMessage('状态值无效'),
  
  query('courseId')
    .optional()
    .isUUID()
    .withMessage('课程ID格式无效'),
  
  query('search')
    .optional()
    .isLength({ min: 1, max: 100 })
    .withMessage('搜索关键词长度必须在1-100个字符之间'),
  
  query('sortBy')
    .optional()
    .isIn(['createdAt', 'publishedAt', 'title', 'startTime', 'endTime'])
    .withMessage('排序字段无效'),
  
  query('sortOrder')
    .optional()
    .isIn(['ASC', 'DESC'])
    .withMessage('排序方向无效')
];

const submitExamValidation = [
  param('id')
    .isUUID()
    .withMessage('考试ID格式无效'),
  
  body('answers')
    .isArray()
    .withMessage('答案必须是数组格式'),
  
  body('answers.*.questionId')
    .isUUID()
    .withMessage('题目ID格式无效'),
  
  body('answers.*.answer')
    .notEmpty()
    .withMessage('答案不能为空'),
  
  body('timeSpent')
    .optional()
    .isInt({ min: 0 })
    .withMessage('用时必须是非负整数')
];

// 工具函数
const handleValidationErrors = (req, res, next) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    const errorMessages = errors.array().map(error => error.msg);
    throw new ValidationError('验证失败', errorMessages);
  }
  next();
};

const buildExamQuery = (queryParams) => {
  const { type, level, status, courseId, search, teacherId } = queryParams;
  const where = {};
  
  if (type) {
    where.type = type;
  }
  
  if (level) {
    where.level = level;
  }
  
  if (status) {
    where.status = status;
  } else {
    // 默认只显示已发布的考试（对于公开接口）
    where.status = 'published';
  }
  
  if (courseId) {
    where.courseId = courseId;
  }
  
  if (teacherId) {
    where.teacherId = teacherId;
  }
  
  if (search) {
    const { Op } = require('sequelize');
    where[Op.or] = [
      { title: { [Op.like]: `%${search}%` } },
      { description: { [Op.like]: `%${search}%` } }
    ];
  }
  
  return where;
};

const checkExamOwnership = async (req, res, next) => {
  try {
    const { id } = req.params;
    const currentUser = req.user;
    
    const exam = await Exam.findByPk(id, {
      include: [
        {
          model: Course,
          as: 'course',
          attributes: ['id', 'title', 'teacherId']
        }
      ]
    });
    
    if (!exam) {
      throw new AppError('考试不存在', 404);
    }
    
    // 检查权限：考试创建者、课程教师或管理员可以操作
    const isOwner = exam.teacherId === currentUser.id;
    const isCourseTeacher = exam.course && exam.course.teacherId === currentUser.id;
    const isAdmin = ['admin', 'super_admin'].includes(currentUser.role);
    
    if (!isOwner && !isCourseTeacher && !isAdmin) {
      throw new AppError('无权限操作此考试', 403);
    }
    
    req.exam = exam;
    next();
  } catch (error) {
    next(error);
  }
};

const checkExamAccess = async (req, res, next) => {
  try {
    const { id } = req.params;
    const currentUser = req.user;
    
    const exam = await Exam.findByPk(id, {
      include: [
        {
          model: Course,
          as: 'course',
          attributes: ['id', 'title']
        }
      ]
    });
    
    if (!exam) {
      throw new AppError('考试不存在', 404);
    }
    
    // 检查考试是否可以参加
    const canTake = await exam.canTake(currentUser.id);
    if (!canTake.allowed) {
      throw new AppError(canTake.reason, 403);
    }
    
    req.exam = exam;
    next();
  } catch (error) {
    next(error);
  }
};

// 路由处理函数

/**
 * @route   GET /api/exams
 * @desc    获取考试列表
 * @access  Public
 */
router.get('/', getExamsValidation, handleValidationErrors, async (req, res, next) => {
  try {
    const {
      page = 1,
      limit = 20,
      sortBy = 'publishedAt',
      sortOrder = 'DESC'
    } = req.query;
    
    const offset = (page - 1) * limit;
    const where = buildExamQuery(req.query);
    
    const { count, rows: exams } = await Exam.findAndCountAll({
      where,
      include: [
        {
          model: User,
          as: 'teacher',
          attributes: ['id', 'username', 'realName', 'avatar']
        },
        {
          model: Course,
          as: 'course',
          attributes: ['id', 'title']
        }
      ],
      limit: parseInt(limit),
      offset,
      order: [[sortBy, sortOrder.toUpperCase()]]
    });
    
    const totalPages = Math.ceil(count / limit);
    
    res.json({
      success: true,
      data: {
        exams,
        pagination: {
          currentPage: parseInt(page),
          totalPages,
          totalItems: count,
          itemsPerPage: parseInt(limit),
          hasNextPage: page < totalPages,
          hasPrevPage: page > 1
        }
      }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   GET /api/exams/my
 * @desc    获取我的考试（教师）
 * @access  Private (Teacher/Admin)
 */
router.get('/my', authenticate, authorize(['teacher', 'admin', 'super_admin']), getExamsValidation, handleValidationErrors, async (req, res, next) => {
  try {
    const {
      page = 1,
      limit = 20,
      sortBy = 'createdAt',
      sortOrder = 'DESC'
    } = req.query;
    
    const offset = (page - 1) * limit;
    const where = buildExamQuery({ ...req.query, teacherId: req.user.id });
    
    // 移除默认的状态过滤，显示所有状态的考试
    delete where.status;
    if (req.query.status) {
      where.status = req.query.status;
    }
    
    const { count, rows: exams } = await Exam.findAndCountAll({
      where,
      include: [
        {
          model: Course,
          as: 'course',
          attributes: ['id', 'title']
        }
      ],
      limit: parseInt(limit),
      offset,
      order: [[sortBy, sortOrder.toUpperCase()]]
    });
    
    const totalPages = Math.ceil(count / limit);
    
    res.json({
      success: true,
      data: {
        exams,
        pagination: {
          currentPage: parseInt(page),
          totalPages,
          totalItems: count,
          itemsPerPage: parseInt(limit),
          hasNextPage: page < totalPages,
          hasPrevPage: page > 1
        }
      }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   GET /api/exams/course/:courseId
 * @desc    获取课程的考试列表
 * @access  Public
 */
router.get('/course/:courseId', param('courseId').isUUID().withMessage('课程ID格式无效'), getExamsValidation, handleValidationErrors, async (req, res, next) => {
  try {
    const { courseId } = req.params;
    const {
      page = 1,
      limit = 20,
      sortBy = 'publishedAt',
      sortOrder = 'DESC'
    } = req.query;
    
    const offset = (page - 1) * limit;
    const where = buildExamQuery({ ...req.query, courseId });
    
    const { count, rows: exams } = await Exam.findAndCountAll({
      where,
      include: [
        {
          model: User,
          as: 'teacher',
          attributes: ['id', 'username', 'realName', 'avatar']
        }
      ],
      limit: parseInt(limit),
      offset,
      order: [[sortBy, sortOrder.toUpperCase()]]
    });
    
    const totalPages = Math.ceil(count / limit);
    
    res.json({
      success: true,
      data: {
        exams,
        pagination: {
          currentPage: parseInt(page),
          totalPages,
          totalItems: count,
          itemsPerPage: parseInt(limit),
          hasNextPage: page < totalPages,
          hasPrevPage: page > 1
        }
      }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   GET /api/exams/:id
 * @desc    获取考试详情
 * @access  Public
 */
router.get('/:id', param('id').isUUID().withMessage('考试ID格式无效'), handleValidationErrors, async (req, res, next) => {
  try {
    const { id } = req.params;
    
    const exam = await Exam.findByPk(id, {
      include: [
        {
          model: User,
          as: 'teacher',
          attributes: ['id', 'username', 'realName', 'avatar']
        },
        {
          model: Course,
          as: 'course',
          attributes: ['id', 'title']
        }
      ]
    });
    
    if (!exam) {
      throw new AppError('考试不存在', 404);
    }
    
    // 如果用户已登录，检查参加权限
    let canTake = null;
    if (req.user) {
      canTake = await exam.canTake(req.user.id);
    }
    
    res.json({
      success: true,
      data: {
        exam,
        canTake
      }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   POST /api/exams
 * @desc    创建考试
 * @access  Private (Teacher/Admin)
 */
router.post('/', authenticate, authorize(['teacher', 'admin', 'super_admin']), createExamValidation, handleValidationErrors, async (req, res, next) => {
  try {
    const examData = {
      ...req.body,
      teacherId: req.user.id
    };
    
    // 如果指定了课程，验证课程是否存在且用户有权限
    if (examData.courseId) {
      const course = await Course.findByPk(examData.courseId);
      if (!course) {
        throw new AppError('指定的课程不存在', 404);
      }
      
      // 检查权限：课程教师或管理员可以创建考试
      if (course.teacherId !== req.user.id && !['admin', 'super_admin'].includes(req.user.role)) {
        throw new AppError('无权限为此课程创建考试', 403);
      }
    }
    
    const exam = await Exam.create(examData);
    
    logger.request('考试创建', {
      examId: exam.id,
      title: exam.title,
      courseId: exam.courseId,
      teacherId: exam.teacherId,
      ip: req.ip
    });
    
    res.status(201).json({
      success: true,
      message: '考试创建成功',
      data: { exam }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   PUT /api/exams/:id
 * @desc    更新考试
 * @access  Private (Exam Owner/Admin)
 */
router.put('/:id', authenticate, updateExamValidation, handleValidationErrors, checkExamOwnership, async (req, res, next) => {
  try {
    const exam = req.exam;
    
    await exam.update(req.body);
    
    logger.request('考试更新', {
      examId: exam.id,
      updatedBy: req.user.id,
      changes: Object.keys(req.body),
      ip: req.ip
    });
    
    res.json({
      success: true,
      message: '考试更新成功',
      data: { exam }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   DELETE /api/exams/:id
 * @desc    删除考试
 * @access  Private (Exam Owner/Admin)
 */
router.delete('/:id', authenticate, param('id').isUUID().withMessage('考试ID格式无效'), handleValidationErrors, checkExamOwnership, async (req, res, next) => {
  try {
    const exam = req.exam;
    
    // 软删除
    await exam.destroy();
    
    logger.request('考试删除', {
      examId: exam.id,
      title: exam.title,
      deletedBy: req.user.id,
      ip: req.ip
    });
    
    res.json({
      success: true,
      message: '考试删除成功'
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   POST /api/exams/:id/publish
 * @desc    发布考试
 * @access  Private (Exam Owner/Admin)
 */
router.post('/:id/publish', authenticate, param('id').isUUID().withMessage('考试ID格式无效'), handleValidationErrors, checkExamOwnership, async (req, res, next) => {
  try {
    const exam = req.exam;
    
    if (exam.status === 'published') {
      throw new AppError('考试已发布', 400);
    }
    
    await exam.publish();
    
    logger.request('考试发布', {
      examId: exam.id,
      title: exam.title,
      publishedBy: req.user.id,
      ip: req.ip
    });
    
    res.json({
      success: true,
      message: '考试发布成功',
      data: { exam }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   POST /api/exams/:id/start
 * @desc    开始考试
 * @access  Private (Student)
 */
router.post('/:id/start', authenticate, param('id').isUUID().withMessage('考试ID格式无效'), handleValidationErrors, checkExamAccess, async (req, res, next) => {
  try {
    const exam = req.exam;
    const { accessCode } = req.body;
    
    // 验证访问码
    if (exam.accessCode && exam.accessCode !== accessCode) {
      throw new AppError('访问码错误', 400);
    }
    
    const attempt = await exam.startAttempt(req.user.id);
    
    logger.request('考试开始', {
      examId: exam.id,
      attemptId: attempt.id,
      userId: req.user.id,
      ip: req.ip
    });
    
    res.json({
      success: true,
      message: '考试开始',
      data: { attempt }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   POST /api/exams/:id/submit
 * @desc    提交考试
 * @access  Private (Student)
 */
router.post('/:id/submit', authenticate, submitExamValidation, handleValidationErrors, async (req, res, next) => {
  try {
    const { id } = req.params;
    const { answers, timeSpent } = req.body;
    
    const exam = await Exam.findByPk(id);
    if (!exam) {
      throw new AppError('考试不存在', 404);
    }
    
    const result = await exam.submitAttempt(req.user.id, answers, timeSpent);
    
    logger.request('考试提交', {
      examId: exam.id,
      userId: req.user.id,
      score: result.score,
      passed: result.passed,
      timeSpent,
      ip: req.ip
    });
    
    res.json({
      success: true,
      message: '考试提交成功',
      data: { result }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   GET /api/exams/:id/attempts
 * @desc    获取考试尝试记录
 * @access  Private (Student - own attempts, Teacher/Admin - all attempts)
 */
router.get('/:id/attempts', authenticate, param('id').isUUID().withMessage('考试ID格式无效'), handleValidationErrors, async (req, res, next) => {
  try {
    const { id } = req.params;
    const currentUser = req.user;
    
    const exam = await Exam.findByPk(id);
    if (!exam) {
      throw new AppError('考试不存在', 404);
    }
    
    let attempts;
    
    // 学生只能查看自己的尝试记录
    if (currentUser.role === 'student') {
      attempts = await exam.getUserAttempts(currentUser.id);
    } else {
      // 教师和管理员可以查看所有尝试记录
      attempts = await exam.getAllAttempts();
    }
    
    res.json({
      success: true,
      data: { attempts }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   GET /api/exams/:id/statistics
 * @desc    获取考试统计信息
 * @access  Private (Exam Owner/Admin)
 */
router.get('/:id/statistics', authenticate, param('id').isUUID().withMessage('考试ID格式无效'), handleValidationErrors, checkExamOwnership, async (req, res, next) => {
  try {
    const exam = req.exam;
    
    const statistics = await exam.getStatistics();
    
    res.json({
      success: true,
      data: { statistics }
    });
  } catch (error) {
    next(error);
  }
});

/**
 * @route   POST /api/exams/:id/reset-attempts
 * @desc    重置用户考试尝试次数
 * @access  Private (Exam Owner/Admin)
 */
router.post('/:id/reset-attempts', authenticate, param('id').isUUID().withMessage('考试ID格式无效'), body('userId').isUUID().withMessage('用户ID格式无效'), handleValidationErrors, checkExamOwnership, async (req, res, next) => {
  try {
    const exam = req.exam;
    const { userId } = req.body;
    
    await exam.resetUserAttempts(userId);
    
    logger.request('考试尝试次数重置', {
      examId: exam.id,
      targetUserId: userId,
      resetBy: req.user.id,
      ip: req.ip
    });
    
    res.json({
      success: true,
      message: '用户考试尝试次数重置成功'
    });
  } catch (error) {
    next(error);
  }
});

module.exports = router;